#pragma once
#include <iostream>
#include "Socket.hpp"
#include <functional>
#include<string>
#include <jsoncpp/json/json.h>

// content_len jsonstring
// 50\r\n{"x": 10, "y" : 20, "oper" : '+'}\r\n
// 50
// {"x": 10, "y" : 20, "oper" : '+'}

using namespace SocketModel;

class Request
{
    public:
    Request(){}
    Request(int x,int y,char oper):_x(x),_y(y),_oper(oper)
    {

    }
    std::string Serialize(){
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root["oper"] = _oper;

        Json::FastWriter writer;
        std::string s = writer.write(root);
        return s;
    }
    bool Deserialize(std::string &in){
        Json::Value root;
        Json::Reader reader;

        bool a = reader.parse(in,root);
        if(a){
            _x = root["x"].asInt();
            _y = root["y"].asInt();
            _oper = root["oper"].asInt();
            return true;
        }
        return false;
    }
    ~Request(){}
    int GetX (){ return _x;}
    int GetY (){ return _y;}
    char GetOper(){return _oper;}
    private:
    int _x;
    int _y;
    char _oper; // + - * / % -> _x _oper _y -> 10 + 20
};
class Response
{
    public:
    Response(){}
    Response(int result,int code):_result(result),_code(code){
    }   
    std::string Serialize(){
        Json::Value root;
        root["result"] = _result;
        root["code"] = _code;
        Json::FastWriter writer;
        std::string s = writer.write(root);
        return s;
    }
    bool Deserialize(std::string s){
        Json::Value root;
        Json::Reader reader;

        reader.parse(s,root);
        _result = root["result"].asInt();
        _code = root["code"].asInt();
        return true;
    }
    void SetResult(int a){
        _result = a;
    }
    void SetCode(int b){
        _code = b;
    }
    void ShowResult()
    {
        std::cout << "计算结果是: " << _result << "[" << _code << "]" << std::endl;
    }
    ~Response(){
    }
    private:
    int _result;// 运算结果，无法区分清楚应答是计算结果，还是异常值
    int _code;// 0:sucess, 1,2,3,4->不同的运算异常的情况
};
std::string sep = "\r\n";

using func_t = std::function<Response (Request&)>;
//读取的时候，必须读取完整报文
//request和reponse必须具有序列化和反序列化功能
class Protocol
{
    public:
    Protocol(){}
    Protocol(func_t func):_func(func){}
    //进行序列化封装
    std::string Encode(const std::string& Jsonstr){
        std::string len = std::to_string(Jsonstr.size());
        return len+sep+Jsonstr+sep;
    }
    // 50\r\n{"x": 10, "y" : 20, "oper" : '+'}\r\n

    ~Protocol(){}
    //判断是否有完整的报文
    // 50\r\n{"x": 10, "y": 20, "oper" : '+'}\r\n
    bool Judecode(std::string& prostr,std::string&package){
        auto pos = prostr.find(sep);
        if(pos == std::string::npos) return false;
        std::string numstr = prostr.substr(0,pos);
        int strlen = std::stoi(numstr);
        int tar_len = strlen + 2*sep.size() + numstr.size();
        if(tar_len>prostr.size()) return false;
        //这就说明至少有一条完整的报文
        package = prostr.substr(pos+sep.size(),strlen);
        prostr.erase(0,tar_len);
        return true;
    }

    //
    bool GetResponse(std::shared_ptr<Socket> &peer,Request& client,InetAddr &server,Response& a){
        std::string serverinfo;
        //发送报文
        peer->Connect(server.GetPort(),server.GetIp());
        //序列化
        std::string clientinfo = Encode(client.Serialize());
        peer->Send(clientinfo);
        
        //接收结果
        //判断是否为完整报文
        std::string Jsonpackage;
        while(true){
            int len = peer->Recv(serverinfo);
            
            if(Judecode(serverinfo,Jsonpackage)){
                a.Deserialize(Jsonpackage);
                return true;
            }
        }
        
    }

    //获取客户端报文并进行业务处理，发送报文，服务端核心代码
    void GetRequest(std::shared_ptr<Socket> &peer,InetAddr &client){
        //读取
        std::string clientinfo;
        while(true){
            int n = peer->Recv(clientinfo);
            if(n>0){
                std::string json_package;
                //完整报文
                if(!Judecode(clientinfo,json_package)){
                    continue;
                }
                //反序列化
                Request req;
                if(!req.Deserialize(json_package)) continue;
                //业务，
                Response res = _func(req);

                //序列化
                std::string jsondata = res.Serialize();
                //封装报文
                std::string senddata = Encode(jsondata);
                //直接发送
                peer->Send(senddata);
            }
            else if(n==0){
                Log(LogLevel::INFO) << "client:" << client.StringAddr() << "Quit!";
                break;
            }
            else{
                Log(LogLevel::WARNING) << "client:" << client.StringAddr() << ", recv error";
                break;
            }
        }
    }
    private:
    func_t _func;
};